package com.jfirer.validator.validation;

import com.jfirer.baseutil.StringUtil;
import com.jfirer.baseutil.reflect.ReflectUtil;
import com.jfirer.jfireel.expression.Expression;

import javax.validation.MessageInterpolator;
import java.util.Locale;
import java.util.Map;
import java.util.ResourceBundle;

public class DefaultMessageInterpolator implements MessageInterpolator
{
    private final ResourceBundle buildIn;
    private final ResourceBundle user;

    public DefaultMessageInterpolator()
    {
        buildIn = ResourceBundle.getBundle("BuildInValidationMessages");
        ResourceBundle user;
        try
        {
            user = ResourceBundle.getBundle("ValidationMessages");
        }
        catch (Exception e)
        {
            user = null;
        }
        this.user = user;
    }

    @Override
    public String interpolate(String messageTemplate, Context context)
    {
        return interpolate(messageTemplate, context, buildIn, user);
    }

    private String interpolate(String messageTemplate, Context context, ResourceBundle buildIn, ResourceBundle user)
    {
        if (messageTemplate == null || messageTemplate.length() == 0)
        {
            return messageTemplate;
        }
        if (messageTemplate.charAt(0) == '{' && messageTemplate.endsWith("}"))
        {
            messageTemplate = messageTemplate.substring(1, messageTemplate.length() - 1);
            if (buildIn.containsKey(messageTemplate))
            {
                messageTemplate = buildIn.getString(messageTemplate);
            }
            else if (user != null && user.containsKey(messageTemplate))
            {
                messageTemplate = user.getString(messageTemplate);
            }
        }
        messageTemplate = resolve(messageTemplate, context.getConstraintDescriptor().getAttributes());
        return messageTemplate;
    }

    @Override
    public String interpolate(String messageTemplate, Context context, Locale locale)
    {
        ResourceBundle buildIn = ResourceBundle.getBundle("BuildIn.ValidationMessages.properties");
        ResourceBundle user    = ResourceBundle.getBundle("ValidationMessages.properties");
        return interpolate(messageTemplate, context, buildIn, user);
    }

    String resolve(String message, Map<String, Object> attributes)
    {
        StringBuilder cache = new StringBuilder();
        int           end   = 0;
        int           index = 0;
        do
        {
            char c = message.charAt(index);
            if (c == '$')
            {
                if (index + 1 < message.length() && message.charAt(index + 1) == '{')
                {
                    end = message.indexOf('}', index);
                    if (end == -1)
                    {
                        throw new UnsupportedOperationException(StringUtil.format("消息:{}存在问题，${没有被包围", message));
                    }
                    else
                    {
                        String script = message.substring(index + 2, end);
                        try
                        {
                            Expression expression = Expression.parse(script);
                            cache.append(expression.calculate(attributes));
                        }
                        catch (Exception e)
                        {
                            ReflectUtil.throwException(e);
                        }
                        index = end + 1;
                    }
                }
            }
            else if (c == '{')
            {
                end = message.indexOf('}', index);
                if (end == -1)
                {
                    throw new UnsupportedOperationException(StringUtil.format("消息:{}存在问题，${没有被包围", message));
                }
                else
                {
                    String script = message.substring(index + 1, end);
                    try
                    {
                        cache.append(Expression.parse(script).calculate(attributes));
                    }
                    catch (Exception e)
                    {
                        ReflectUtil.throwException(e);
                    }
                    index = end + 1;
                }
            }
            else
            {
                cache.append(c);
                index += 1;
            }
        } while (index < message.length());
        return cache.toString();
    }
}
